var _assert = require('assert');

var _assert2 = _interopRequireDefault(_assert);

var _jsonwebtoken = require('jsonwebtoken');

var _jsonwebtoken2 = _interopRequireDefault(_jsonwebtoken);

var _thinkHelper = require('think-helper');

var _thinkHelper2 = _interopRequireDefault(_thinkHelper);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

/**
 * 业务层基类
 */
class BaseService extends think.Service {
    /**
     * 角色数据范围过滤
     * tableName   (必传)当前过滤的表名
     * userInfo  (必传)用户信息
     * option 选项(可选){
     *    attributes:`field1,field2,field3`,或者['field1','field2','field3']
             page:{
                 start:0,  //第几页
                 limit:0   //每页显示多少条
             }
     * }
     * 返回false代表没有数据权限过滤
     */
    dataScopeFilter(tableName, userInfo, option) {
        var _this = this;

        return _asyncToGenerator(function* () {
            (0, _assert2.default)(typeof tableName === 'string', 'tableName must be a String');
            (0, _assert2.default)(ObjectUtils.isObject(userInfo), 'userInfo must be a Object');
            let defaultOption = {
                // attributes: `${tableName}.*`,
                attributes: '*',
                ORG_TABLE_NAME: 'sys_org',
                USER_TABLE_NAME: 'sys_user'
                // page:{
                //     start:null,
                //     limit:null
                // }
            };
            const DB = _this.db;
            const model = DB[tableName];
            const orgModel = DB['sys_org'];
            (0, _assert2.default)(model, 'table does not exist');
            const { userId, orgId, roleList } = userInfo;
            const administrator = think.config('administrator');
            option = _thinkHelper2.default.extend({}, defaultOption, option);
            const ORG_TABLE_NAME = option.ORG_TABLE_NAME;
            const USER_TABLE_NAME = option.USER_TABLE_NAME;
            // if (option.attributes.includes('*')) {
            //     option.attributes = `${tableName}.*`;
            // }
            let attributes = option.attributes;
            let pageStr = '';
            if ('page' in option) {
                let start = option.page.start;
                let limit = option.page.limit;
                if (start && limit) {
                    pageStr = ` limit ${(start - 1) * limit},${limit}`;
                }
            }
            // 数据范围（1：所有数据；2：所在部门及以下数据；3：所在部门数据；4：仅本人数据；5：按明细设置）
            /**
             * 1、所有数据： 无where条件,直接返回所有数据。
             * 2、所在部门及以下数据   like当前用户所在部门的parent_ids + 当前用户的'部门id, or部门id=部门id'
             * 3、所在部门数据      =当前用户的部门id
             * 4、仅本人数据　　　　仅跟自己相关的业务数据。
             * 5、按明细设置 跨机构授权,多个角色的授权为并集的关系。
             */

            // 数据权限过滤，多个角色权限范围之间为或者关系。
            const dataScopeArry = yield _this.getRoleDataScope(roleList);
            if (dataScopeArry.length === 0) {
                return false;
            }
            const dataScopeNum = ArrayUtils.findArrayMin(dataScopeArry);
            let sql = 'SELECT ';
            let field = attributes;
            // let newAttr;
            if (Array.isArray(attributes)) {
                // newAttr = attributes.map((item, index, arr) => {
                //     return `${tableName}.${item}`;
                // });
                field = attributes.join();
            }
            sql += field;
            //如果是超级管理员或者数据权重为1，则跳过数据权限过滤
            if (dataScopeNum === 1 || administrator.includes(userId)) {
                sql += ` FROM ${tableName}`;
                pageStr ? sql += pageStr : sql += '';
                return _this.CrudService.querySql(sql);
            }

            let orgIds = null;
            let customWhereStr = '';
            //如果存在自定义授权，则先构造自定义where条件
            if (dataScopeArry.includes(5)) {
                orgIds = yield _this.findCustomAuthOrgIds(roleList);
                customWhereStr = ` OR org.id in(${orgIds})`;
            }
            //根据表名构造表连接，用户表,机构表,业务表。
            if (tableName === USER_TABLE_NAME) {
                sql += ` FROM ${tableName} us INNER JOIN ${ORG_TABLE_NAME} org ON us.org_id = org.id`;
            } else if (tableName === ORG_TABLE_NAME) {
                sql += ` FROM ${tableName} org`;
            } else {
                sql += ` FROM ${tableName} INNER JOIN ${USER_TABLE_NAME} us ON ${tableName}.create_by = us.id INNER JOIN ${ORG_TABLE_NAME} org ON us.org_id = org.id`;
            }
            //根据数据权限构造不同的where条件
            switch (dataScopeNum) {
                case 2:
                    //所在部门及以下
                    const object = yield orgModel.findById(orgId, {
                        attributes: ['parent_ids']
                    });
                    const orgParentIds = object.parent_ids;
                    sql += ` WHERE org.parent_ids LIKE '%${orgParentIds}${orgId},%' or org.id=${orgId}`;
                    break;
                case 3:
                    //所在部门
                    sql += ` WHERE org.id = ${orgId}`;
                    break;

                case 4:
                    //本人数据
                    if (tableName === USER_TABLE_NAME) {
                        sql += ` WHERE us.id="${userId}"`;
                    } else if (tableName === ORG_TABLE_NAME) {
                        sql += ` WHERE org.id="${orgId}"`;
                    } else {
                        sql += ` WHERE ${tableName}.create_by="${userId}"`;
                        // customWhereStr ? sql = `SELECT ${field} FROM ${tableName} INNER JOIN ${USER_TABLE_NAME} us ON ${tableName}.create_by = us.id INNER JOIN ${ORG_TABLE_NAME} org ON us.org_id = org.id WHERE ${tableName}.create_by="${userId}" ${customWhereStr}` : sql = `SELECT ${field} FROM ${tableName} WHERE create_by="${userId}"`;
                    }
                    break;
                case 5:
                    //自定义授权
                    customWhereStr = ` WHERE org.id in(${orgIds})`;
                    break;
            }

            sql += customWhereStr;
            sql += pageStr;
            const list = yield _this.CrudService.querySql(sql);
            if (pageStr) {
                return {
                    rows: list,
                    count: option.page.limit
                };
            }
            return list;
        })();
    }

    /**
     * 查询自定义权限的机构ids
     * @param roleList
     * @returns {Promise<string>}
     * @private
     */
    findCustomAuthOrgIds(roleList) {
        var _this2 = this;

        return _asyncToGenerator(function* () {
            const Op = _this2.db.Sequelize.Op;
            const result = yield _this2.db['sys_role'].findAll({
                where: { id: { [Op.in]: roleList } },
                attributes: ['auth_org_ids'],
                raw: true
            });
            let arry = [];
            for (let value of result) {
                if (!think.isEmpty(value.auth_org_ids)) {
                    arry = arry.concat(value.auth_org_ids.split(','));
                }
            }
            const orgIds = ArrayUtils.unique(arry).join();
            return orgIds;
        })();
    }

    /**
     * 查询自定义权限的机构ids
     * @param roleList
     * @returns {Promise<Array>}
     * @private
     */
    findCustomAuthOrgIdsArray(roleList) {
        var _this3 = this;

        return _asyncToGenerator(function* () {
            const Op = _this3.db.Sequelize.Op;
            const result = yield _this3.db['sys_role'].findAll({
                where: { id: { [Op.in]: roleList } },
                attributes: ['auth_org_ids'],
                raw: true
            });
            let arry = [];
            for (let value of result) {
                if (!think.isEmpty(value.auth_org_ids)) {
                    arry = arry.concat(value.auth_org_ids.split(','));
                }
            }
            const orgIds = ArrayUtils.unique(arry);
            return orgIds;
        })();
    }

    /**
     * 数据过滤，返回where条件
     * 如果返回1，则在业务代码里没有where条件
     * 如果返回4,则目标表里带create_by=userid的条件
     * 否则返回正确的where条件在sys_org表里
     * @param userInfo
     * @param isOrm
     * @returns {Promise<*>}
     */
    getDataScopeWhere(userInfo, isOrm) {
        var _this4 = this;

        return _asyncToGenerator(function* () {
            const db = _this4.db;
            const Op = db.Sequelize.Op;
            const orgModel = db['sys_org'];
            const administrator = think.config('administrator');
            const { roleList, orgId } = userInfo;
            let whereObj = {};
            let whereStr = '';
            if (!think.isEmpty(roleList) && !think.isEmpty(orgId)) {
                const dataScopeNumAry = yield _this4.getRoleDataScope(roleList);
                const dataScopeNum = ArrayUtils.findArrayMin(dataScopeNumAry);
                //如果是超级管理员或者数据权重为1，则跳过数据权限过滤
                if (dataScopeNum === 1 || administrator.includes(userInfo)) {
                    return 1;
                }
                //如果存在自定义授权，则先构造自定义where条件

                let otherWhere = null;
                if (dataScopeNumAry.includes(5)) {
                    const orgIds = yield _this4.findCustomAuthOrgIdsArray(roleList);
                    otherWhere = { id: { [Op.in]: orgIds } };
                    // orgIds = await this.findCustomAuthOrgIds(roleList);
                    // customWhereStr = ` OR org.id in(${orgIds})`
                }
                switch (dataScopeNum) {
                    case 2:
                        const object = yield orgModel.findById(orgId, {
                            attributes: ['parent_ids']
                        });
                        const orgParentIds = object.parent_ids;
                        if (isOrm) {
                            if (otherWhere) {
                                whereObj = {
                                    [Op.or]: [{ parent_ids: { [Op.like]: `%${orgParentIds}${orgId},%` } }, { id: orgId }, otherWhere]
                                };
                            } else {
                                whereObj = {
                                    [Op.or]: [{ parent_ids: { [Op.like]: `%${orgParentIds}${orgId},%` } }, { id: orgId }]
                                };
                            }

                            return whereObj;
                        }
                        whereStr = `WHERE sys_org.parent_ids LIKE '%${orgParentIds}${orgId},%' or sys_org.id=${orgId}`;
                        return whereStr;
                    case 3:
                        if (isOrm) {
                            if (otherWhere) {
                                whereObj = {
                                    [Op.or]: [{ id: orgId }, otherWhere]
                                };
                            } else {
                                whereObj = { id: orgId };
                            }

                            return whereObj;
                        }
                        whereStr = `WHERE sys_org.id = ${orgId}`;
                        return whereStr;
                    case 4:
                        return 4;
                    case 5:
                        if (otherWhere) {
                            whereObj = otherWhere;
                        }
                        return whereObj;

                }
            }
            return null;
        })();
    }

    /**
     * 扫描所有用户，根据权限标识查询有权限用户的id,
     * @returns {Array}
     */
    getAllUserAuthByPermission(permission) {
        var _this5 = this;

        return _asyncToGenerator(function* () {
            const allUserInfo = [];
            const queue = []; //队列人员
            const roleUserIds = yield _this5.db['sys_role_user'].findAll({ group: 'userid', attributes: ['userid'] });
            for (let value of roleUserIds) {
                allUserInfo.push((yield _this5.getUserInfo(value.userid)));
            }
            for (let value of allUserInfo) {
                const authVal = value.menuList.find(function (item) {
                    return item.permission === permission;
                });
                if (authVal) {
                    queue.push(value.id);
                }
            }
            return queue;
        })();
    }

    /**
     * 获取用户完全信息
     * @param userId
     * @returns {Promise<{Object}>}
     */
    getUserInfo(userId) {
        var _this6 = this;

        return _asyncToGenerator(function* () {
            (0, _assert2.default)(typeof userId === 'string' && userId, 'userId must not null && is String');
            const user = yield _this6.db['sys_user'].findOne({
                where: {
                    id: userId
                },
                attributes: { exclude: ['password', 'del_flag'] }
            });
            const role = yield _this6.db['sys_role_user'].findAll({
                where: {
                    userid: userId
                },
                attributes: ['roleid']
            });
            const roleIds = role.map(function (r) {
                return r.roleid;
            });
            const menuList = yield _this6.getRoleMenu(roleIds, userId);
            const userInfo = Object.assign({}, user.toJSON());
            userInfo.roleList = roleIds;
            userInfo.menuList = menuList;
            return userInfo;
        })();
    }

    getParentIdsByOrgId(orgId) {
        var _this7 = this;

        return _asyncToGenerator(function* () {
            return _this7.db['sys_org'].findOne({ where: { org_id: orgId } });
        })();
    }

    /**
     * 获取角色访问权限
     * @param roleList Array 角色ids
     * @returns {Promise<*>}
     */
    getRoleAuth(roleList) {
        var _this8 = this;

        return _asyncToGenerator(function* () {
            (0, _assert2.default)(Array.isArray(roleList), 'roleList type should eq "Array"');
            let roles = JSON.stringify(roleList).replace('[', '').replace(']', '');
            const sqlAuth = `SELECT mu.href FROM sys_menu mu INNER JOIN sys_role_menu rmu ON mu.id = rmu.menuid WHERE rmu.roleid in (${roles})`;
            const roleAuth = yield _this8.CrudService.querySql(sqlAuth);
            let obj = {
                href: []
            };
            for (let value of roleAuth) {
                obj.href.push(value.href);
            }
            return obj;
        })();
    }

    /**
     *
     * @param roleList
     * @returns {Promise<{required: boolean, message: string, trigger: string}[][]>}
     */
    getRoleDataScope(roleList) {
        var _this9 = this;

        return _asyncToGenerator(function* () {
            (0, _assert2.default)(Array.isArray(roleList), 'roleList type should eq "Array"');

            const roleDataScope = yield _this9.db['sys_role'].findAll({
                where: {
                    id: {
                        [_this9.db.Sequelize.Op.in]: roleList
                    }
                },
                attributes: ['data_scope'],
                raw: true
            });
            return roleDataScope.map(function (item) {
                return item.data_scope;
            });
            // let roles = JSON.stringify(roleList).replace('[', '').replace(']', '');
            // let sql = `SELECT data_scope FROM sys_role WHERE id in(${roles})`;
            // const dataScopeList = await this.CrudService.querySql(sql);

            // const ary = dataScopeList.map((item) => {
            //     return item.data_scope;
            // });
            // return ary;
            // if (ary.includes(5) && ary.length > 1) {
            //     return [Number(ArrayUtils.findArrayMin(ary)), 5]
            // }
            // return Number(ArrayUtils.findArrayMin(ary));
        })();
    }

    /**
     * 根据角色ids获取角色菜单列表
     * @param roleList Array  角色ids
     * @param userId  String userId
     * @returns {Promise<*>}
     */
    getRoleMenu(roleList, userId) {
        var _this10 = this;

        return _asyncToGenerator(function* () {
            (0, _assert2.default)(Array.isArray(roleList), 'roleList type should eq "Array"');
            (0, _assert2.default)(typeof userId === 'string', 'userId must be a String');
            const administrator = think.config('administrator');
            let roles = JSON.stringify(roleList).replace('[', '').replace(']', '');
            let sql = '';
            if (administrator.includes(userId)) {
                sql = `SELECT * FROM sys_menu WHERE menu_source=1 GROUP BY id ORDER BY menu_order`;
                // sql = `SELECT * FROM sys_menu WHERE is_show=1 AND menu_source=1`;
            } else {
                // sql = `SELECT * FROM sys_menu mu INNER JOIN sys_role_menu rmu ON mu.id = rmu.menuid WHERE rmu.roleid in (${roles}) AND is_show=1 AND menu_source=1`;
                sql = `SELECT * FROM sys_menu mu INNER JOIN sys_role_menu rmu ON mu.id = rmu.menuid WHERE rmu.roleid in (${roles}) AND menu_source=1 GROUP BY mu.id ORDER BY menu_order`;
            }

            return _this10.CrudService.querySql(sql);
        })();
    }

    /**
     * 根据用户信息生成一个token
     * @param userInfo
     * @returns {*}token
     */
    getToken(userInfo) {
        const tokenConfig = think.config('token');
        const privateKey = tokenConfig.privateKey; // （密钥）
        const expiresIn = tokenConfig.expiresIn;
        const token = _jsonwebtoken2.default.sign(userInfo, privateKey, {
            expiresIn: expiresIn // 过期时间
        });
        return token;
    }

    getTokenForApp(userInfo) {
        const tokenConfig = think.config('token');
        const privateKey = tokenConfig.privateKey; // （密钥）
        const expiresIn = tokenConfig.expiresInApp;
        const token = _jsonwebtoken2.default.sign(userInfo, privateKey, {
            expiresIn: expiresIn // 过期时间
        });
        return token;
    }

    /**
     *  根据机构id获取直属公司
     * @param user
     * @returns {Promise<Object>}
     */
    getUserDirectCompany(orgId) {
        var _this11 = this;

        return _asyncToGenerator(function* () {
            (0, _assert2.default)(orgId, 'orgId must be a not empty');
            const orgModel = _this11.db['sys_org'];
            const OP = _this11.db.sequelize.Op;
            let orgInfo = null;
            const orgResult = yield orgModel.findOne({
                where: {
                    id: orgId
                },
                raw: true
            });
            if (!think.isEmpty(orgResult)) {
                //如果当前用户的所在的组织机构是公司，则直接返回该公司。
                if (orgResult.org_type === 1) {
                    return orgResult;
                }
                const parentIds = orgResult.parent_ids;
                if (parentIds) {
                    const parentIdsAry = parentIds.substr(0, parentIds.length - 1).split(',');
                    //查询和过滤树路径上的所有组织机构，只返回公司信息
                    const orgList = yield orgModel.findAll({
                        where: {
                            id: {
                                [OP.in]: parentIdsAry
                            },
                            org_type: 1
                        },
                        raw: true
                    });
                    if (!think.isEmpty(orgList)) {
                        //将树路径字符串数组转成数字数组，方便后面比较。
                        const numParentIdsAry = parentIdsAry.map(function (item) {
                            return parseInt(item);
                        });

                        const orgIdsAry = orgList.map(function (item) {
                            return item.id;
                        });
                        //以树路径用为参考和公司数组做比较找出交集，数组最末尾的值就是当前用户的直属公司。
                        const intersection = ArrayUtils.intersection(numParentIdsAry, orgIdsAry);
                        orgInfo = orgList.filter(function (item) {
                            return item.id === intersection[intersection.length - 1];
                        });
                    }
                }
            }
            if (Array.isArray(orgInfo)) {
                return orgInfo[0];
            }
            return orgInfo;
        })();
    }

    isAdmin(user) {
        if (!think.isEmpty(user)) {
            return think.config('administrator').includes(user.userId);
        }
        return null;
    }

    /**
     * 根据pinyin或汉字搜索记录
     */

    /**
     *  缓存角色权限
     * @param userId  用户Id     type: string
     * @param roleList 角色列表  type:array
     * @returns {Promise<void>}
     */
    // async cacheRolePermission(roleList, userId) {
    //     assert(Array.isArray(roleList), 'roleList type should eq "Array"');
    //     let roles = JSON.stringify(roleList);
    //     roles = roles.replace('[', '').replace(']', '');
    //     let sql = `SELECT mu.href, mu.permission, mu.menu_source, rl.data_scope FROM sys_menu mu INNER JOIN sys_role_menu rmu ON mu.id = rmu.menuid INNER JOIN sys_role rl ON rl.id = rmu.roleid WHERE rl.id in (${roles})`;
    //     try {
    //         let rolePermissionList = await this.CrudService.querySql(sql);
    //         // console.log(rolePermissionList);
    //         if (think.redis.isReady()) {
    //             const redisCli = think.redis.client;
    //             // think.redis.client.set(`userInfo:rolePerm:${userId}`, JSON.stringify(rolePermissionList), 'EX', expiresIn);
    //             redisCli.set(`userInfo:rolePerm:${userId}`, JSON.stringify(rolePermissionList));
    //         } else {
    //             throw new Error('连接redis失败')
    //         }
    //     } catch (e) {
    //         this.exceptionService.handleError(e);
    //     }
    //
    // }


}

module.exports = BaseService;